package org.dmcs.linguistics.labs.parkingmeter.factory;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import org.dmcs.linguistics.labs.parkingmeter.DeterministicFiniteAutomaton;
import org.dmcs.linguistics.labs.parkingmeter.IAutomaton;
import org.dmcs.linguistics.labs.parkingmeter.states.ParkingMeterState;
import org.dmcs.linguistics.labs.parkingmeter.input.symbols.ParkingMeterInputSymbol;
import org.dmcs.linguistics.labs.parkingmeter.input.symbols.SymbolStatePair;

/**
 * Klasa "factory" konfigurujaca i zwraqcajaca DFA reprezentujacy zadany parkomat.
 * @author Zielony 
 * @version 1.0
 */
public class ParkingMeterFactory {
	/**
	 * Zwraca: <code>DeterministicFiniteAutomaton</code> zbudowany i skonfigurowany tak, aby reprezentowal
	 * zadany parkomat.
	 * @return <code>DeterministicFiniteAutomaton</code> zbudowany i skonfigurowany tak, aby reprezentowal
	 * zadany parkomat.
	 */
	public static IAutomaton getParkingMeter() {
		/*
		 * Tworzenie tabeli przejsc jako HashMap - relatywnie lepsza wydajnosc.
		 */
		Map<SymbolStatePair<ParkingMeterInputSymbol, ParkingMeterState>, ParkingMeterState> transitionTable = 
				new HashMap<SymbolStatePair<ParkingMeterInputSymbol, ParkingMeterState>, ParkingMeterState>();
		
		//S0 + I1 = S1
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_1, ParkingMeterState.S0), 
				ParkingMeterState.S1);
		
		//S0 + I2 = S2
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_2, ParkingMeterState.S0), 
				ParkingMeterState.S2);
		
		//S0 + I5 = S5
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_5, ParkingMeterState.S0), 
				ParkingMeterState.S5);
		
		
		//S1 + I1 = S2
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_1, ParkingMeterState.S1), 
				ParkingMeterState.S2);
		
		//S1 + I2 = S3
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_2, ParkingMeterState.S1), 
				ParkingMeterState.S3);
		
		//S1 + I5 = S6
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_5, ParkingMeterState.S1), 
				ParkingMeterState.S6);
		
		//S2 + I1 = S3
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_1, ParkingMeterState.S2), 
			ParkingMeterState.S3);
		
		//S2 + I2 = S4
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_2, ParkingMeterState.S2), 
				ParkingMeterState.S4);
		
		//S2 + I5 = S7
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_5, ParkingMeterState.S2), 
				ParkingMeterState.S7);
		
		//S3 + I1 = S4
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_1, ParkingMeterState.S3), 
				ParkingMeterState.S4);
				
		//S3 + I2 = S5
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_2, ParkingMeterState.S3), 
				ParkingMeterState.S5);
		
		//S3 + I5 = S0
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_5, ParkingMeterState.S3), 
				ParkingMeterState.S0);
		
		//S4 + I1 = S5
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_1, ParkingMeterState.S4), 
				ParkingMeterState.S5);
						
		//S4 + I2 = S6
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_2, ParkingMeterState.S4), 
				ParkingMeterState.S6);
				
		//S4 + I5 = S0
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_5, ParkingMeterState.S4), 
				ParkingMeterState.S0);
		
		//S5 + I1 = S6
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_1, ParkingMeterState.S5), 
				ParkingMeterState.S6);
						
		//S5 + I2 = S7
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_2, ParkingMeterState.S5), 
				ParkingMeterState.S7);
				
		//S5 + I5 = S0
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_5, ParkingMeterState.S5), 
				ParkingMeterState.S0);
		
		//S6 + I1 = S7
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_1, ParkingMeterState.S6), 
				ParkingMeterState.S7);
						
		//S6 + I2 = S0
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_2, ParkingMeterState.S6), 
				ParkingMeterState.S0);
				
		//S6 + I5 = S0
		transitionTable.put(new SymbolStatePair(ParkingMeterInputSymbol.INPUT_5, ParkingMeterState.S6), 
				ParkingMeterState.S0);
		
		/*
		 * Budowa DFA reprezentujacego zadany parkomat.
		 */
		IAutomaton<ParkingMeterInputSymbol, ParkingMeterState> parkingMeter = 
				new  DeterministicFiniteAutomaton<ParkingMeterInputSymbol, ParkingMeterState>(
						ParkingMeterState.S0, transitionTable);
		
		return parkingMeter;
	}
}